package com.spsa.negocio.servicios;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.spsa.Parametros;
import com.spsa.excepciones.ServicioException;
import com.spsa.negocio.utilidades.SingletonDatos;
import com.spsa.negocio.utilidades.UtilCorreo;
import com.spsa.persistencia.entidades.Destinatario;
import com.spsa.persistencia.entidades.Reporte;

@Stateless
public class ServicioCorreoProgramado {

	static final Logger logger = LogManager.getLogger(ServicioCorreoProgramado.class.getName());

	@EJB
	private SingletonDatos singletonDatos;
	@EJB
	private ServicioGeneracionReportes servicioReportes;
	private Properties properties;
	private Session sesionCorreo;

	@Schedule(second = "0", minute = "0", hour = "7", dayOfMonth = "*", persistent=false)
	public void enviarReporteTiendas() {
		while (true) {
			try {
				logger.info("Se comenzara a enviar los reportes por correo");
				List<Reporte> reportes = servicioReportes.generarReporteEstadoTiendas();
				enviarReportesPorCorreo(reportes);
				logger.info("Los reportes fueron enviados correctamente");
				return;
			} catch (MessagingException e) {
				logger.error("No se pudo enviar los reportes del estado de las tiendas por e-mail", e); //$NON-NLS-1$
				logger.info("Se esperara 15 segundos para volver a intentar enviar los reportes");
				esperarSiguienteIntento();

			} catch (ServicioException e) {
				logger.error("No se pudo generar los reportes del estado de las tiendas", e); //$NON-NLS-1$
				logger.info("Se esperara 15 segundos para volver a intentar enviar los reportes");
				esperarSiguienteIntento();
			}
		}
	}

	public void esperarSiguienteIntento() {
		try {
			Thread.sleep(15000);
		} catch (Exception e) {
			logger.error(e);
		}
	}

	public void enviarReportesPorCorreo(Reporte reporte) {
		try {
			List<Reporte> reportes = new ArrayList<Reporte>();
			reportes.add(reporte);
			enviarReportesPorCorreo(reportes);
		} catch (MessagingException e) {
			logger.error("Error al enviar reportes de tiendas por e-mail", e); //$NON-NLS-1$
		}
	}

	private void enviarReportesPorCorreo(List<Reporte> reportes) throws MessagingException, AddressException {
		conectarseServidorCorreo();
		Message message = crearMensaje(reportes);
		enviarMensaje(message);
	}

	private void conectarseServidorCorreo() {
		properties = new Properties();
		properties.put("mail.smtp.host", Parametros.get("ServicioCorreoProgramado.HOST")); //$NON-NLS-1$ //$NON-NLS-2$
		properties.put("mail.smtp.port", Parametros.get("ServicioCorreoProgramado.PUERTO")); //$NON-NLS-1$ //$NON-NLS-2$
		sesionCorreo = Session.getInstance(properties);
	}

	private Message crearMensaje(List<Reporte> reportes) throws MessagingException, AddressException {
		Message mensaje = new MimeMessage(sesionCorreo);
		crearEncabezadoMensaje(mensaje);
		crearCuerpoMensaje(mensaje, reportes);
		return mensaje;
	}

	private void enviarMensaje(Message message) throws MessagingException {
		Transport.send(message);
	}

	private void crearEncabezadoMensaje(Message mensaje) throws AddressException, MessagingException {
		mensaje.setFrom(new InternetAddress(Parametros.get("ServicioCorreoProgramado.REMITENTE"))); //$NON-NLS-1$

		List<Destinatario> destinatarios = singletonDatos.getDestinatarios();
		InternetAddress direccionesCorreo[] = UtilCorreo.obtenerDirecciones(destinatarios);

		mensaje.addRecipients(Message.RecipientType.BCC, direccionesCorreo);
		mensaje.setSubject("Reporte tiendas en Rojo " + new Date()); //$NON-NLS-1$
	}

	private void crearCuerpoMensaje(Message mensaje, List<Reporte> reportes) throws MessagingException,
			AddressException {
		Multipart archivosAdjuntos = new MimeMultipart();

		for (int i = 0; i < reportes.size(); i++) {
			MimeBodyPart archivoAdjunto = new MimeBodyPart();
			FileDataSource fds = new FileDataSource(reportes.get(i).getRutaReporte());
			archivoAdjunto.setDataHandler(new DataHandler(fds));
			archivoAdjunto.setFileName(fds.getName());
			archivosAdjuntos.addBodyPart(archivoAdjunto);
		}

		mensaje.setContent(archivosAdjuntos);
	}
}
